# 画课程测试试题的图

import matplotlib.pyplot as plt
import numpy as np

from qiskit import QuantumCircuit, transpile
from qiskit.visualization import plot_bloch_multivector
from qiskit.circuit import ParameterVector
from qiskit.quantum_info import Pauli
from qiskit.primitives import Estimator


# 产生随机转动值（仿真对qubit的干扰噪音）
random_rotations = np.array([np.pi/2])
print("random_rotations=", random_rotations)

# 设置修正转动值
theta_rotations = np.array([np.pi/2, np.pi/2])
print("theta_rotations=", theta_rotations)

# 定义量子线路，其中rx ry rz为旋转门，遵从右手定则（例如对于rx，右手大拇指指向x轴方向，其他手指则为旋转方向）
qc = QuantumCircuit(1,1)
beta = ParameterVector('β', 1)
qc.rx(beta[0], 0)
qc.barrier()

# 定义受神经网络控制的量子线路，其中theta为控制的参数
theta = ParameterVector('θ', 2)
qc.rz(theta[0], 0)
qc.ry(theta[1], 0)
qc.barrier()
# 拷贝一份电路加入测量，并没有实际作用，只是便于显示电路全貌。之所以不直接在原qc上加测量，是因为后面用到Estimator计算测量结果期望和梯度，电路中不能有测量操作
qc_measure = QuantumCircuit.copy(qc)
qc_measure.measure(0, 0)

# 绑定随机旋转的3个角度参数
qc = qc.bind_parameters({beta: random_rotations})
qc_measure = qc_measure.bind_parameters({beta: random_rotations})

# 显示量子线路
qc_measure.draw('mpl')

# 计算量子线路测量的梯度和损失
estimator = Estimator()
print("E=",estimator.run(qc, Pauli('Z'), theta_rotations).result().values[0])

plt.show()